package com.bobi.tfca.viewmodel

import android.app.Application
import android.view.View
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.bobi.doublewillow.utils.SPUtil
import com.bobi.tfca.constants.CodeCategoryEnum
import com.bobi.tfca.network.ApiResponse
import com.bobi.tfca.network.RequestBuilder
import com.bobi.tfca.network.api.MemberAPI
import com.bobi.tfca.network.response.ActivityResponse
import com.bobi.tfca.network.response.ArticleResponse
import com.bobi.tfca.network.response.ChatRoomResponse
import com.bobi.tfca.network.response.MemberProfileResponse
import com.bobi.tfca.network.response.MemberResponse
import com.bobi.tfca.network.response.MessageResponse
import com.bobi.tfca.util.LogUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import retrofit2.Call

/**
 * 公共的ViewModel
 * 共享到所有的Fragment中，在BaseFragment中就集成了这个PublicViewModel，可以在Activity加载时把这个公共的ViewModel进行初始化，
 * 类似一个单例的使用，可以初始化一次一些需要Context的对象，不用反复获取Context减小开销，并且不是单例进行Context的持有，避免不规范操作，
 * 比如初始化一次API类和一些数据库操作工具类，在别的Fragment中就可以反复的进行使用，从而减少不必要对象的反复创建，
 *
 * 不建议创建多个Public对象使得一个Fragment中进行多个ViewModel的操作，反而会让代码结构变得冗余和复杂，
 * 尽量两个ViewModel，一个fragment本身的ViewModel，一个公共的PublicViewModel
 */
class PublicViewModel(application: Application) : AndroidViewModel(application) {

    val requestBuilder = RequestBuilder(application.applicationContext)
    val spUtil = SPUtil(application.applicationContext)
    fun <T> request(APIType: Class<T>): T = requestBuilder.getAPI(APIType)
    fun <T> Call<T>.getResponse(process: suspend (flow: Flow<ApiResponse<T>>) -> Unit) {
        viewModelScope.launch(Dispatchers.IO) {
            requestBuilder.apply {
                process(requestBuilder.getResponse {
                    this@getResponse.execute()
                })
            }
        }
    }

    // 聊天室信息保持，所处的聊天室
    val chatRoom by lazy {
        MutableLiveData(ChatRoomResponse())
    }

    // 新信件
    val newLetterNum by lazy {
        MutableLiveData(0)
    }

    // 新通知
    val newNotificationNum by lazy {
        MutableLiveData(0)
    }

    // 活动详情信息保存，所处的活动
    val activity by lazy {
        MutableLiveData(ActivityResponse())
    }

    var organizeActivity = ActivityResponse()


    // 信件、通知保持，所处的消息
    val message by lazy {
        MutableLiveData(MessageResponse())
    }

    // 文化展示文章保持
    val article by lazy {
        MutableLiveData(ArticleResponse())
    }

    // 会员信息保持，非当前用户，主要用于会员管理
    val member by lazy {
        MutableLiveData(MemberResponse())
    }

    // 回复信息保持
    var reply = ""

    // 验证码用途
    var codeCategory: CodeCategoryEnum? = null

    // 会员档案信息保持，用于注册
    var memberProfile = MemberProfileResponse()

    // 账号和新密码
    var account = ""
    var newPassword = ""
    var resetEmail = ""

    val visiblePageElements by lazy {
        MutableLiveData(ArrayList<String>())
    }


    fun resetMessage() {
        message.value = MessageResponse()
    }

    fun resetChatRoom() {
        chatRoom.value = ChatRoomResponse()
    }

    fun resetActivity() {
        activity.value = ActivityResponse()
    }

    fun resetOrganizeActivity() {
        organizeActivity = ActivityResponse()
    }

    fun resetArticle() {
        article.value = ArticleResponse()
    }

    fun resetMember() {
        member.value = MemberResponse()
    }

    fun resetProfile() {
        memberProfile = MemberProfileResponse()
    }

    fun resetReply() {
        reply = ""
    }

    fun resetResetPasswordInfo() {
        codeCategory = null
        account = ""
        newPassword = ""
        resetEmail = ""
    }

    fun resetRegisterInfo() {
        resetProfile()
        codeCategory = null
    }

    fun resetVisiblePageElements() {
        visiblePageElements.value = ArrayList()
    }

    // 返回元素可见性的函数
    fun getElementVisibility(elementId: String): Int {
        return if (visiblePageElements.value!!.contains(elementId)) {
            View.VISIBLE
        } else {
            View.GONE
        }
    }

    fun getCurrentAllMenus() {
        request(MemberAPI::class.java).getMemberMenus().getResponse {
            it.collect {
                when (it) {
                    is ApiResponse.Error -> {
                        LogUtil.e(it.errMsg)
                    }

                    ApiResponse.Loading -> LogUtil.e("Loading")
                    is ApiResponse.Success -> {
                        withContext(Dispatchers.Main) {
                            val result = it.data?.data ?: arrayListOf()
                            visiblePageElements.value = result
                            LogUtil.i("menus:${visiblePageElements.toString()}")
                        }
                    }
                }
            }
        }
    }
}